#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <unistd.h>
#include <jsoncpp/json/json.h>

namespace protocol_ns
{
    const std::string SEP = "\r\n";

    // 我们把tcp中读到的报文，可能读到半个，也可能读到1个半等， TCP 粘报问题
    // 解决TCP的粘报问题
    std::string Encode(const std::string &json_str)
    {
        int json_str_len = json_str.size();
        std::string proto_str = std::to_string(json_str_len);
        proto_str += SEP;
        proto_str += json_str;
        proto_str += SEP;
        return proto_str;
    }
    // "len"\r\n"{
    // "len"\r\n"{             }"
    // "len"\r\n"{             }"\r\n;
    // "len"\r\n"{             }"\r\n"len";
    // "len"\r\n"{             }"\r\n"len"\r\n"{             }";
    // "len"\r\n"{             }"\r\n"len"\r\n"{             }"\r\n
    std::string Decode(std::string &inbuffer)
    {
        auto pos = inbuffer.find(SEP);
        if (pos == std::string::npos)
            return std::string();
        std::string len_str = inbuffer.substr(0, pos);
        if (len_str.empty())
            return std::string();
        int packlen = std::stoi(len_str);

        int total = packlen + len_str.size() + 2 * SEP.size();
        if (inbuffer.size() < total)
            return std::string();

        std::string package = inbuffer.substr(pos + SEP.size(), packlen);
        inbuffer.erase(0, total);
        return package;
    }
    // 我们的协议的样子:
    // 报文 = 报头+有效载荷
    // "有效载荷的长度"\r\n"有效载荷"\r\n
    // "len"\r\n"_x _op _y"\r\n  -> len: 有效载荷的长度，约定\r\n是分隔符，不参与统计

    // 就是结构化数据 能像网络中直接发送吗？不能，也不建议
    // 其他问题？class Reqeust req(10, 20, "*"); req->字节？ 直接发送req对象，class Reqeust req

    class Response
    {
    public:
        Response()
        {
        }
        Response(int error, std::string body)
            : _error(error),
              _body(body)
        {
        }
        bool Serialize(std::string *out)
        {
            // 转换成为字符串
            Json::Value root;
            root["Error"] = _error;
            root["Body"] = _body;

            Json::FastWriter writer;
            // Json::StyledWriter writer;
            *out = writer.write(root);
            return true;
        }
        bool Deserialize(const std::string &in) // 你怎么知道你读到的in 就是完整的一个请求呢？
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (!res)
                return false;

            _error = root["Error"].asInt();
            _body = root["Body"].asString();
            return true;
        }

    public:
        int _error;
        std::string _body;
    };

    class Request
    {
    public:
        Request()
        {
        }
        Request(std::string method, std::string url, std::string version, std::string accept, std::string accept_Encoding, std::string cookies)
            : _method(method),
              _url(url),
              _version(version),
              _accept(accept),
              _accept_Encoding(accept_Encoding),
              _cookies(cookies)
        {
        }
        bool Serialize(std::string *out)
        {
            // 转换成为字符串
            Json::Value root;
            root["Method"] = _method;
            root["Url"] = _url;
            root["Version"] = _version;
            root["Accept"] = _accept;
            root["Accept_Encoding"] = _accept_Encoding;
            root["Cookies"] = _cookies;

            Json::FastWriter writer;
            // Json::StyledWriter writer;
            *out = writer.write(root);
            return true;
        }
        bool Deserialize(const std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (!res)            
                return false;

            _method = root["Method"].asString();
            _url = root["Url"].asString();
            _version = root["Version"].asString();
            _accept = root["Accept"].asString();
            _accept_Encoding = root["Accept_Encoding"].asString();
            _cookies = root["Cookies"].asString();
            return true;
        }

    public:
        std::string _method;          // 请求方法
        std::string _url;             // 请求URL
        std::string _version;         // 浏览器版本
        std::string _accept;          // 浏览器可接受的数据类型
        std::string _accept_Encoding; // 浏览器编码
        std::string _cookies;         // 客户端cookies
    };

    // class Factory
    // {
    // public:
    //     Factory()
    //     {
    //         srand(time(nullptr) ^ getpid());
    //         opers = "+/*/%^&|";
    //     }
    //     std::shared_ptr<Request> BuildRequest()
    //     {
    //         int x = rand() % 10 + 1;
    //         usleep(x * 10);
    //         int y = rand() % 5; // [01,2,3,4]
    //         usleep(y * x * 5);
    //         char oper = opers[rand() % opers.size()];
    //         std::shared_ptr<Request> req = std::make_shared<Request>(x, y, oper);
    //         return req;
    //     }
    //     std::shared_ptr<Response> BuildResponse()
    //     {
    //         return std::make_shared<Response>();
    //     }
    //     ~Factory()
    //     {
    //     }

    // private:
    //     std::string opers;
    // };
}
